<template>
  <el-form-item
    class="release-form-item"
    v-if="editorState"
    :label="`${itemName}：`"
    :prop="`${formKey}.${index}.value`"
    :rules="rules">
    <!--下拉框  -->
    <template v-if="itemType === FORM_TYPE_ENUMS.SELECT">
      <el-col :span="20">
        <el-select v-model="editorValue" placeholder="请选择" class="input-block" @change="handleSelectChange">
          <el-option v-for="item in listData" :key="item.value" :label="item.name" :value="item" />
        </el-select>
      </el-col>
    </template>
    <!--文本框  -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.INPUT">
      <el-col :span="20">
        <el-input v-model="editorValue" @change="handleInputChange"/>
      </el-col>
    </template>
    <!--时间段  -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.TIMES">
      <el-col :span="editorData.remarks ? 24 : 20">
        <el-date-picker
          :class="{
            'input-block': !editorData.remarks
          }"
          v-model="editorValue"
          format="yyyy-MM-dd"
          type="daterange"
          :placeholder="`请选择${itemName}`"
          :picker-options="pickerOptions"
          @change="handleDatesChange"/>
        <span class="form-help" v-if="editorData.remarks">{{editorData.remarks}}</span>
      </el-col>
    </template>
    <!--单个时间  -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.TIME">
      <el-col :span="20">
        <el-date-picker class="input-block"
          v-model="editorValue"
          type="date"
          format="yyyy-MM-dd"
          :placeholder="`请选择${itemName}`"
          :picker-options="pickerOptions"
          @change="handleDateChange"/>
      </el-col>
    </template>
    <!--地址  -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.ADDRESS">
      <el-col :span="20">
        <el-row :gutter="20">
          <el-col :span="12">
            <!-- 地址选个更改根据label改变去触发 保证label已更新 -->
            <address-cascader class="input-block"
              placeholder="请选择省市"
              :grade="2"
              ref="adddressEl"
              v-model="addressHead"
              :label.sync="addressLabel"/>
          </el-col>
          <el-col :span="12">
            <el-input class="input-block"
              placeholder="请输入详细地址"
              v-model="addressDetail"
              @change="handleAddressChange"/>
          </el-col>
        </el-row>
      </el-col>
    </template>
    <!-- 多值文本框 -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.INPUTS">
      <el-col :span="20">
        <input-group :max-item="6" v-model="editorValue" @change="handleInputsChange"/>
      </el-col>
    </template>
    <!-- 单选 -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.RADIO">
      <el-col :span="24">
        <el-radio-group v-model="editorValue" @change="handleRadioChange">
          <el-radio
            v-for="item in itemData"
            :key="item.value"
            :label="item.name">{{item.name}}
          </el-radio>
        </el-radio-group>
        <span class="form-help" v-if="editorData.remarks">{{editorData.remarks}}</span>
      </el-col>
    </template>
    <!-- 多选 -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.CHECKBOX">
      <el-col :span="24">
        <el-checkbox-group v-model="editorValue" @change="handleCheckboxChange">
          <el-checkbox
            v-for="(item, index) in itemData"
            :label="item"
            :key="item.name">{{item.name}}</el-checkbox>
        </el-checkbox-group>
      </el-col>
    </template>
    <!-- 级联 -->
    <template v-else-if="itemType === FORM_TYPE_ENUMS.CASCADER">
      <el-col :span="20">
        <el-cascader class="input-block"
          :grade="2"
          :props="cascaderProps"
          :options="cascaderList"
          v-model="editorValue"
          @change="handleCasChange"
          @active-item-change="handleCasItemChange"/>
      </el-col>
    </template>
  </el-form-item>
</template>
<script>
  /**
  * data.type 为定义类型 @param{type 1-下拉框 2-输入框 3-时间 4-地址}
  * data.rules 为验证规则
  * data.name 为字段key
  * data.nameText 为字段文本
  * data.value 为输入值  单选 下拉多选 等需要特殊  如文本框则 值设为 与valueText相等
  * data.valueText 为值文本
  */
  import InputGroup from 'modules/components/InputGroup'
  import AddressCascader from 'modules/components/AddressCascader'
  import serviceApi from 'api/service'
  import { FORM_TYPE_ENUMS, DATA_TYPE_ENUMS } from '../constant'

  import emitter from 'utils/emitter.js'
  export default {
    mixins: [emitter],
    components: {
      InputGroup,
      AddressCascader
    },
    props: {
      isEditor: Boolean,
      data: Object,
      formKey: String,
      index: Number
    },
    computed: {
      itemName () {
        // 字段中文名 标签名
        return this.editorData.attrName
      }
    },
    watch: {
      editorData () {
        this.$emit('update:data', this.editorData)
      },
      addressLabel (newVl) {
        // 地址updateLbale 后与change事件，所以这里做一下处理
        this.handleAddressChange()
      }
    },
    created () {
      this.initItemData()
      // window.tyler11 = this
    },
    data () {
      let {editorData, rules, itemType, editorValue} = this.initBasicData()
      return {
        editorValues: [],
        editorState: !1, // url模式下 需要获取数据才能编辑
        editorData: editorData,
        editorValue: editorValue,
        FORM_TYPE_ENUMS: FORM_TYPE_ENUMS,
        itemData: {},
        itemType: itemType, // 控件类型 1-下拉 2-文本 3-日期 4-地址
        rules: rules, // 验证规则
        // 日期
        pickerOptions: {
          disabledDate (time) {
            return time.getTime() < Date.now() - 8.64e7
          }
        },
        // 地址
        addressLabel: '',
        addressHead: [],
        addressDetail: '',
        // 下拉框数据
        listData: [],
        // 级联数据
        // cascader: [],
        cascaderList: [],
        cascaderState: !0, // 默认第一级有级联 触发二级时再判断
        cascaderProps: {
          label: 'name'
        },
        isFirstLoad: !0, // 是否初始化渲染
        valueToTextObj: {} // 级联级-对应文本
      }
    },
    methods: {
      initBasicData () {
        // 由于生命周期  这里不能使用computed中的变量
        // 初始化value  和规则值
        let message = ''
        let editorData = {}
        let editorValue = ''
        let rules = []
        let itemName = this.data.attrName
        let itemType = this.data.showModel - 0
        let isHasChild = Boolean(this.data.children)
        itemType = isHasChild ? FORM_TYPE_ENUMS.CASCADER : itemType // 级联处理
        switch (itemType) {
          case FORM_TYPE_ENUMS.SELECT: // 下拉
            message = `请选择${itemName}`
            editorValue = {}
            break
          case FORM_TYPE_ENUMS.INPUT: // 输入框
            message = `${itemName}不能为空`
            editorValue = ''
            break
          case FORM_TYPE_ENUMS.TIMES: // 时间段
            message = `请选择${itemName}`
            editorValue = []
            break
          case FORM_TYPE_ENUMS.TIME: // 单个时间
            message = `请选择${itemName}`
            editorValue = ''
            break
          case FORM_TYPE_ENUMS.ADDRESS:  // 地址
            message = `请选择${itemName}和填写详细地址`
            editorValue = []
            break
          case FORM_TYPE_ENUMS.INPUTS: // 多值输入框
            message = `请输入${itemName}`
            editorValue = []
            break
          case FORM_TYPE_ENUMS.RADIO: // 单选
            message = `请选择${itemName}`
            editorValue = ''
            break
          case FORM_TYPE_ENUMS.CHECKBOX: // 多选
            message = `请选择${itemName}`
            editorValue = []
            break
          case FORM_TYPE_ENUMS.CASCADER: // 级联
            message = `请选择${itemName}`
            editorValue = []
            break
        }
        // 初始化规则
        rules.push({
          required: this.data.isRequired,
          // required: !1,
          message: message
        })
        editorData = Object.assign(this.data, {value: '', valueText: ''})
        return {
          editorData,
          editorValue,
          itemType,
          rules
        }
      },
      initItemData () {
        /**
         * 数据类型 1-url 2-text 3-json
         * 1、一般为下拉框需要通过url获取数据
         * 2、一般为文本框
         * 3、一般为多选框
         */
        let jsonData
        let type = this.editorData.dataType - 0
        let attrValue = this.editorData.attrValue
        // 处理数据 强制将文本类型数据转换
        if (this.itemType === FORM_TYPE_ENUMS.INPUT || this.itemType === FORM_TYPE_ENUMS.TIMES || this.itemType === FORM_TYPE_ENUMS.INPUTS || this.itemType === FORM_TYPE_ENUMS.ADDRESS) {
          type = DATA_TYPE_ENUMS.TEXT
        }
        switch (type) {
          case DATA_TYPE_ENUMS.URL:
            // {url, text, value}
            jsonData = JSON.parse(this.editorData.attrValue)
            this.getItemData(jsonData)
            break
          case DATA_TYPE_ENUMS.TEXT:
            this.setTextItemData()
            this.itemData = attrValue
            this.editorState = !0
            break
          case DATA_TYPE_ENUMS.JSON:
            // {data: [], text, value}
            jsonData = JSON.parse(attrValue)
            this.setListItemData(jsonData)
            break
          default:
            this.itemData = attrValue
        }
      },
      getItemData (config) {
        // {url, text, value} URL模式下 约定的格式
        config.url && serviceApi.dict(config.url).then(({data}) => {
          // 请求完成 启用编辑模式
          config.data = data
          this.setListItemData(config)
        })
      },
      setListItemData ({data = [], text, value}) {
        this.editorState = !0
        data = data.map(item => {
          // url模式下 JSON对象的value为数据的value_key
          // url模式下 JSON对象的text为数据的name_key
          item.name = item[text]
          item.value = item[value]
          item.valueObj = { name: item[text], value: item[value] }
          this.valueToTextObj[item.value] = item.name // 第一级
          return {
            ...item,
            children: [] // 级联默认第一级肯定有子集
          }
        })
        switch (this.itemType) {
          case FORM_TYPE_ENUMS.SELECT:
            this.listData = data
            if (this.isEditor) {
              let {editorValues, editorTexts} = this.editorData
              let editItem = data.find(k => k.value + '' === editorValues[0] + '')
              this.editorValue = editItem || this.editorValue
              this.setEditorVal(editorValues, editorTexts)
            } else if (!this.editorData.isRequired) {
              this.setEditorVal([])
            }
            break
          case FORM_TYPE_ENUMS.RADIO: // 单选
            this.itemData = data
            if (this.isEditor) {
              let { editorTexts } = this.editorData
              this.editorValue = editorTexts[0]
            } else { // 非编辑默认值
              this.editorValue = data[0].name
            }
            this.handleRadioChange(this.editorValue)
            break
          case FORM_TYPE_ENUMS.CHECKBOX: // 多选
            this.itemData = data
            setTimeout(_ => {
              if (this.isEditor) {
                let { editorTexts } = this.editorData
                this.editorValue = data.filter(k => editorTexts.includes(k.name))
                this.handleCheckboxChange(this.editorValue)
              }
            }, 200)
            break
          case FORM_TYPE_ENUMS.CASCADER: // 级联
            this.cascaderList = data
            if (this.isEditor) {
              let {editorValues} = this.editorData
              let curIndex = 0
              let casItem = data.find((k, kIndex) => {
                let flag = Boolean(k.value - 0 === editorValues[0] - 0)
                curIndex = flag ? kIndex : curIndex
                return flag
              })
              this.handleCasItemChange([casItem.value])
            }
            break
        }
      },
      setTextItemData () {
        switch (this.itemType) {
          case FORM_TYPE_ENUMS.INPUT:
            if (this.isEditor) {
              let values = this.editorData.editorValues
              this.editorValue = values[0]
              this.setEditorVal(values)
            } else if (!this.editorData.isRequired) {
              this.setEditorVal([])
            }
            break
          case FORM_TYPE_ENUMS.INPUTS:
            if (this.isEditor) {
              let values = this.editorData.editorValues
              this.editorValue = values
              this.setEditorVal(values)
            } else if (!this.editorData.isRequired) {
              this.setEditorVal([])
            }
            break
          case FORM_TYPE_ENUMS.TIMES:
            if (this.isEditor) {
              let values = this.editorData.editorValues
              this.editorValue = values
              this.setEditorVal(values)
            } else if (!this.editorData.isRequired) {
              this.setEditorVal([])
            }
            break
          case FORM_TYPE_ENUMS.ADDRESS:
            if (this.isEditor) {
              let {editorValues, editorTexts} = this.editorData
              this.addressHead = editorValues.slice(0, editorValues.length - 1).map(k => k - 0) // 转为int类型
              this.addressDetail = editorValues.slice(editorValues.length - 1)[0]
              this.setEditorVal(editorValues, editorTexts)
            }
            break
        }
      },
      handleSelectChange (newVal) { // 下拉框处理
        // 下拉框 不会清空数据
        this.setEditorVal([newVal.value + ''], [newVal.name])
      },
      handleInputChange (newVal) { // 文本框处理
        // 文本框会清空 需要处理变更为''时清空数据setEditorVal
        if (!newVal) {
          this.deleteEditorVal()
          return !1
        }
        this.setEditorVal([newVal])
      },
      handleDatesChange (newVal) { // 时间段框处理
        if (!newVal) {
          this.deleteEditorVal()
          return !1
        }
        let dateArr = newVal.split(' - ')
        this.setEditorVal(dateArr)
      },
      handleDateChange (newVal) { // 单日期框处理
        if (!newVal) {
          this.deleteEditorVal()
          return !1
        }
        this.setEditorVal([newVal])
      },
      handleAddressChange () { // 地址处理
        if (this.addressHead.length && this.addressDetail) {
          let value = [...this.addressHead, this.addressDetail]
          let valueText = [...this.addressLabel, this.addressDetail]
          this.setEditorVal(value, valueText)
        } else {
          this.deleteEditorVal()
        }
      },
      handleRadioChange (newVal) { // 单选框改变处理
        let item = this.itemData.find(item => item.name === newVal)
        this.setEditorVal([item.value], [newVal])
      },
      handleCheckboxChange (newVal = []) { // 多选框改变
        if (newVal.length) {
          let valuesArr = []
          let valueTextsArr = []
          newVal.map(item => {
            valuesArr.push(item.value)
            valueTextsArr.push(item.name)
          })
          this.setEditorVal(valuesArr, valueTextsArr)
        } else {
          this.deleteEditorVal()
        }
      },
      handleInputsChange (newVal) {
        newVal = newVal.filter(k => k)
        if (newVal.length) { // 有数据 直接提交
          this.setEditorVal(newVal) // 只传一个 则两个值相同赋值
        } else if (!this.editorData.isRequired) {
          newVal = newVal.length ? newVal : ['']
          this.setEditorVal(newVal)
        } else {
          this.deleteEditorVal()
        }
      },
      handleCasChange (newCasVal) {
        // 级联末级触发时间
        // 初始化
        let value = []
        let valueText = []
        value = newCasVal
        newCasVal.forEach(item => {
          valueText.push(this.valueToTextObj[item])
          // value.push(item.value)
          // valueText.push(item.name)
        })
        this.setEditorVal(value, valueText)
      },
      setEditorVal (value, valueText) {
        // console.log('统一处理赋值', value, valueText)
        // 统一处理赋值
        this.editorData.value = value
        // 如果valueText 不传 则把value赋值进去
        this.editorData.valueText = valueText || value
        this.broadcast('ElFormItem', 'el.form.change', value)
      },
      deleteEditorVal () {
        this.editorData.value = ''
        this.editorData.valueText = ''
        this.broadcast('ElFormItem', 'el.form.change', [])
      },
      handleCasItemChange (newVal) {
        // 级联中间级点击触发
        let casId = newVal[newVal.length - 1] // 级联id 用于获取数据
        newVal.forEach((k, index) => {
          if (!index) {
            this.curCasData = this.editorData.children
          } else {
            this.curCasData = this.curCasData.children
          }
        })
        let childCasData = this.curCasData.children // 获取子集 如果有子集则添加给下一级 继而下一级到这里时继续判断进行
        let isLastCas = !childCasData // 预算下一级 是否是最后一及
        // 暂时只做URL模式
        let { url, text, value, parentValueType = 0 } = JSON.parse(this.curCasData.attrValue)
        // jsonData 中有一个字段parentValueType
        // 值为1表示所有子集都根据顶级value取获取数据  其他取父级
        // 两级的没有parentValueType字段
        if (parentValueType - 0 === 1) {
          this.casId = newVal[0] // 首级
        } else {
          this.casId = casId // 末级
        }
        url += this.casId
        serviceApi.dict(url).then(({data = []}) => {
          // debugger
          data = data.map(item => {
            item.name = item[text]
            item.value = item[value]
            item.valueObj = { name: item[text], value: item[value] }
            this.valueToTextObj[item.value] = item.name // 子集 暂定由value定 valueText 默认value相同 则valueText相同
            return {
              ...item,
              children: isLastCas ? undefined : [] // 末级则无
            }
          })
          if (newVal.length === 1) {
            let itemIndex = this.cascaderList.findIndex(item => item.value === newVal[0])
            let cascaderItem = Object.assign(this.cascaderList[itemIndex], {
              children: data.length ? data : undefined
            })
            this.$set(this.cascaderList, itemIndex, cascaderItem)
          } else {
            // debugger
            let itemObj = this.cascaderList
            newVal.forEach((item, index) => {
              let itemIndex = itemObj.findIndex(k => k.value === item)
              if (index === 0) {
                itemObj = itemObj[itemIndex].children
              } else if (index < newVal.length - 1) {
                itemObj = itemObj[itemIndex].children
              } else {
                itemObj[itemIndex].children = data.length ? data : undefined
              }
            })
          }
          if (this.isEditor && this.isFirstLoad) {
            // 最后一级
            let value = this.curCasData.editorValues ? this.curCasData.editorValues[0] - 0 : data[0].value
            let newSelectValue = [...newVal, value]
            this.editorValue = newSelectValue
            if (!isLastCas) {
              this.handleCasItemChange(newSelectValue)
            } else {
              this.isFirstLoad = !1
              this.handleCasChange(newSelectValue)
            }
          }
        })
      }
    }
  }
</script>
<style lang="scss">
.release-form-item.el-form-item {
  .el-form-item__content {
    .el-input.input-tips{
      width: 290px;
    }
  }
}
</style>
